#include "ov5648.h"
#include "hal_i2c.h"
#include "i2c.h"
#include "hal_gpio.h"
#include "hal.h"
#include "hal_dvp.h"
#include "../isp_xc6130/xc6130.h"

//#include "i2c_ll.h"


static STRU_CAMERA_REG_VALUE OV5648mipi_2592_1944[]={
	//OV5648_2592X1944_SET
	
	
0x0100,0x00,
0x0103,0x01,


              
0x3001,0x00,
0x3002,0x00,
0x3011,0x02,
0x3018,0x4c,
0x3022,0x00,
0x3034,0x1a,
0x3035,0x21,
0x3036,0x56,
0x3037,0x03,
0x3038,0x00,
0x3039,0x00,
0x303a,0x00,
0x303b,0x19,
0x303c,0x11,
0x303d,0x30,
0x3105,0x11,
0x3106,0x05,
0x3304,0x28,
0x3305,0x41,
0x3306,0x30,
0x3308,0x00,
0x3309,0xc8,
0x330a,0x01,
0x330b,0x90,
0x330c,0x02,
0x330d,0x58,
0x330e,0x03,
0x330f,0x20,
0x3300,0x00,
0x3503,0x07,
0x3601,0x33,
0x3602,0x00,
0x3611,0x0e,
0x3612,0x2b,
0x3614,0x50,
0x3620,0x33,
0x3622,0x00,
0x3630,0xad,
0x3631,0x00,
0x3632,0x94,
0x3633,0x17,
0x3634,0x14,
0x3704,0xc0,
0x3705,0x2a,
0x3708,0x66,
0x3709,0x12,
0x370b,0x23,
0x370c,0xc3,
0x370d,0x00,
0x370e,0x00,
0x371c,0x07,
0x3739,0xd2,
0x373c,0x00,
0x3826,0x03,
0x3829,0x00,
0x382b,0x0b,
0x3830,0x00,
0x3836,0x00,
0x3837,0x00,
0x3838,0x00,
0x3839,0x04,
0x383a,0x00,
0x383b,0x01,
0x3b00,0x00,
0x3b02,0x08,
0x3b03,0x00,
0x3b04,0x04,
0x3b05,0x00,
0x3b06,0x04,
0x3b07,0x08,
0x3b08,0x00,
0x3b09,0x02,
0x3b0a,0x04,
0x3b0b,0x00,
0x3b0c,0x3d,
0x3f01,0x0d,
0x3f0f,0xf5,
0x4000,0x89,
0x4001,0x02,
0x4002,0x45,
0x4004,0x02,
0x4005,0x18,
0x4006,0x08,
0x4007,0x10,
0x4008,0x00,
0x4300,0xf8,
0x4303,0xff,
0x4304,0x00,
0x4307,0xff,
0x4520,0x00,
0x4521,0x00,
0x4511,0x22,
0x4800,0x14,
0x481f,0x3c,
0x4826,0x00,
0x4837,0x18,
0x4b00,0x06,
0x4b01,0x0a,
0x5000,0xff,
0x5001,0x00,
0x5002,0x41,
0x5003,0x0a,
0x5004,0x00,
0x5043,0x00,
0x5013,0x00,
0x501f,0x03,
0x503d,0x00,
0x5180,0x08,
0x5a00,0x08,
0x5b00,0x01,
0x5b01,0x40,
0x5b02,0x00,
0x5b03,0xf0,
0x0100,0x01,
0x4837,0x1d,
//0x4009,0x06,
0x3821,0x08, //   mirror
0x3820,0x46, 

};

static STRU_CAMERA_REG_VALUE OV5648mipi_default_regs[]={
   //OV5648_1280X960_SET
	
	
  0x0100, 0x00, // Software Standy
	0x0103, 0x01, // Software Reset

	0x3001, 0x00, // D[7:0] set to input
	0x3002, 0x00, // D[11:8] set to input
	0x3011, 0x02, // Drive strength 2x
	0x3018, 0x4c, // MIPI 2 lane
	0x3022, 0x00,
	0x3034, 0x1a, // 10-bit mode
	0x3035, 0x21, // PLL
	0x3036, 0x56, // PLL  68.8M
	0x3037, 0x03, // PLL
	0x3038, 0x00, // PLL
	0x3039, 0x00, // PLL
	0x303a, 0x00, // PLLS
	0x303b, 0x19, // PLLS
	0x303c, 0x11, // PLLS
	0x303d, 0x30, // PLLS
	0x3105, 0x11,
	0x3106, 0x05, // PLL
	0x3304, 0x28,
	0x3305, 0x41,
	0x3306, 0x30,
	0x3308, 0x00,
	0x3309, 0xc8,
	0x330a, 0x01,
	0x330b, 0x90,
	0x330c, 0x02,
	0x330d, 0x58,
	0x330e, 0x03,
	0x330f, 0x20,
	0x3300, 0x00,
  0x3503, 0x07, // gain has no delay, manual agc/aec
	0x3601, 0x33, // analog control
	0x3602, 0x00, // analog control
	0x3611, 0x0e, // analog control
	0x3612, 0x2b, // analog control
	0x3614, 0x50, // analog control
	0x3620, 0x33, // analog control
	0x3622, 0x00, // analog control
	0x3630, 0xad, // analog control
	0x3631, 0x00, // analog control
	0x3632, 0x94, // analog control
	0x3633, 0x17, // analog control
	0x3634, 0x14, // analog control
	0x3704, 0xc0, // analog control
	0x3705, 0x2a, // analog control
	0x3708, 0x66, // analog control
	0x3709, 0x52, // analog control
	0x370b, 0x23, // analog control
	0x370c, 0xc3, // analog control
	0x370d, 0x00, // analog control
	0x370e, 0x00, // analog control
	0x371c, 0x07, // analog control
	0x3739, 0xd2, // analog control
	0x373c, 0x00,
	0x3826, 0x03,
	0x3829, 0x00,
	0x382b, 0x0b,
	0x3830, 0x00,
	0x3836, 0x00,
	0x3837, 0x00,
	0x3838, 0x00,
	0x3839, 0x04,
	0x383a, 0x00,
	0x383b, 0x01,
	0x3b00, 0x00, // strobe off
	0x3b02, 0x08, // shutter delay
	0x3b03, 0x00, // shutter delay
	0x3b04, 0x04, // frex_exp
	0x3b05, 0x00, // frex_exp
	0x3b06, 0x04,
	0x3b07, 0x08, // frex inv
	0x3b08, 0x00, // frex exp req
	0x3b09, 0x02, // frex end option
	0x3b0a, 0x04, // frex rst length
	0x3b0b, 0x00, // frex strobe width
	0x3b0c, 0x3d, // frex strobe width
	0x3f01, 0x0d,
	0x3f0f, 0xf5,
	0x4000, 0x89, // blc enable
	0x4001, 0x02, // blc start line
	0x4002, 0x45, // blc auto, reset frame number = 5
	0x4004, 0x02, // black line number
	0x4005, 0x18, // blc normal freeze
	0x4006, 0x08,
	0x4007, 0x10,
	0x4008, 0x00,
	0x4300, 0xf8,
	0x4303, 0xff,
	0x4304, 0x00,
	0x4307, 0xff,
	0x4520, 0x00,
	0x4521, 0x00,
	0x4511, 0x22,
	0x4800, 0x14, // MIPI line sync enable
	0x481f, 0x3c, // MIPI clk prepare min
	0x4826, 0x00, // MIPI hs prepare min
	0x4837, 0x18, // MIPI global timing
	0x4b00, 0x06,
	0x4b01, 0x0a,
	0x5000, 0xff, // bpc on, wpc on
	0x5001, 0x00, // awb disable
	0x5002, 0x41, // win enable, awb gain enable
	0x5003, 0x0a, // buf en, bin auto en
	0x5004, 0x00, // size man off
	0x5043, 0x00,
	0x5013, 0x00,
	0x501f, 0x03, // ISP output data
	0x503d, 0x00, // test pattern off
	0x5180, 0x08, // manual wb gain on
	0x5a00, 0x08,
	0x5b00, 0x01,
	0x5b01, 0x40,
	0x5b02, 0x00,
	0x5b03, 0xf0,
	0x0100, 0x01, // wake up from software sleep
	0x4837, 0x1d, // MIPI global timing


	0x3036, 0x67, // preview pclk=68.8M
	0x3708, 0x66,
	0x3709, 0x52,
	0x370c, 0xc3,
	0x3800, 0x00, // x start = 0
	0x3801, 0x00, // x start
	0x3802, 0x00, // y start = 0
	0x3803, 0x00, // y start
	0x3804, 0x0a, // xend = 2623
	0x3805, 0x3f, // xend
	0x3806, 0x07, // yend = 1955
	0x3807, 0xa3, // yend
	0x3808, 0x05, // x output size = 1296
	0x3809, 0x10, // x output size
	0x380a, 0x03, // y output size = 972
	0x380b, 0xcc, // y output size
	0x380c, 0x0b, // hts = 2816
	0x380d, 0x00, // hts
	0x380e, 0x03, // vts = 992
	0x380f, 0xE0, // vts
	0x3810, 0x00, // isp x win = 8
	0x3811, 0x08, // isp x win
	0x3812, 0x00, // isp y win = 4
	0x3813, 0x04, // isp y win
	0x3814, 0x31, // x inc
	0x3815, 0x31, // y inc
	0x3817, 0x00, // hsync start
	0x3820, 0x0e, // flip off, v bin off
	0x3821, 0x01, // mirror on, h bin on
	0x4004, 0x02, // black line number
	0x4005, 0x18, // blc normal freeze
	0x4050, 0x37, // blc normal freeze
	0x4051, 0x8f, // blc normal freeze
	0x4837, 0x1d, // MIPI global timing
	0x0100, 0x01, //Stream On 
};

static STRU_CAMERA_REG_VALUE OV5648_1920_1080_30fps[] =
{
    //OV5648_1920x1080_SET
        
        
     0x0103, 0x01,
    0x3001, 0x00,
    0x3002, 0x00,
    0x3011, 0x02,
    0x3017, 0x05,
    0x3018, 0x4c,
    0x301c, 0xd2,
    0x3022, 0x00,
    0x3034, 0x1a,
    0x3035, 0x21,
    0x3036, 0x69,
    0x3037, 0x03,
    0x3038, 0x00,
    0x3039, 0x00,
    0x303a, 0x00,
    0x303b, 0x19,
    0x303c, 0x11,
    0x303d, 0x30,
    0x3105, 0x11,
    0x3106, 0x05,
    0x3304, 0x28,
    0x3305, 0x41,
    0x3306, 0x30,
    0x3308, 0x00,
    0x3309, 0xc8,
    0x330a, 0x01,
    0x330b, 0x90,
    0x330c, 0x02,
    0x330d, 0x58,
    0x330e, 0x03,
    0x330f, 0x20,
    0x3300, 0x00,
    0x3500, 0x00,
    0x3501, 0x45,
    0x3502, 0x00,
    0x3503, 0x07,
    0x350a, 0x00,
    0x350b, 0x40,
    0x3601, 0x33,
    0x3602, 0x00,
    0x3611, 0x0e,
    0x3612, 0x2b,
    0x3614, 0x50,
    0x3620, 0x33,
    0x3622, 0x00,
    0x3630, 0xad,
    0x3631, 0x00,
    0x3632, 0x94,
    0x3633, 0x17,
    0x3634, 0x14,
    0x3704, 0xc0,
    0x3705, 0x2a,
    0x3708, 0x63,
    0x3709, 0x12,
    0x370b, 0x23,
    0x370c, 0xcc,
    0x370d, 0x00,
    0x370e, 0x00,
    0x371c, 0x07,
    0x3739, 0xd2,
    0x373c, 0x00,
    0x3800, 0x01,
    0x3801, 0x50,
    0x3802, 0x01,
    0x3803, 0xb2,
    0x3804, 0x08,
    0x3805, 0xef,
    0x3806, 0x05,
    0x3807, 0xf1,
    0x3808, 0x07,
    0x3809, 0x80,
    0x380a, 0x04,
    0x380b, 0x38,
    0x380c, 0x09,
    0x380d, 0xc4,
    0x380e, 0x04,
    0x380f, 0x60,
    0x3810, 0x00,
    0x3811, 0x10,
    0x3812, 0x00,
    0x3813, 0x04,
    0x3814, 0x11,
    0x3815, 0x11,
    0x3817, 0x00,
    0x3820, 0x40,
    0x3821, 0x06,
    0x3826, 0x03,
    0x3829, 0x00,
    0x382b, 0x0b,
    0x3830, 0x00,
    0x3836, 0x00,
    0x3837, 0x00,
    0x3838, 0x00,
    0x3839, 0x04,
    0x383a, 0x00,
    0x383b, 0x01,
    0x3b00, 0x00,
    0x3b02, 0x08,
    0x3b03, 0x00,
    0x3b04, 0x04,
    0x3b05, 0x00,
    0x3b06, 0x04,
    0x3b07, 0x08,
    0x3b08, 0x00,
    0x3b09, 0x02,
    0x3b0a, 0x04,
    0x3b0b, 0x00,
    0x3b0c, 0x3d,
    0x3f01, 0x0d,
    0x3f0f, 0xf5,
    0x4000, 0x89,
    0x4001, 0x02,
    0x4002, 0x45,
    0x4004, 0x04,
    0x4005, 0x18,
    0x4006, 0x08,
    0x4007, 0x10,
    0x4008, 0x00,
    0x4050, 0x6e,
    0x4051, 0x8f,
    0x4300, 0xf8,
    0x4303, 0xff,
    0x4304, 0x00,
    0x4307, 0xff,
    0x4520, 0x00,
    0x4521, 0x00,
    0x4511, 0x22,
    0x4801, 0x0f,
    0x4814, 0x2a,
    0x481f, 0x3c,
    0x4823, 0x3c,
    0x4826, 0x00,
    0x481b, 0x3c,
    0x4827, 0x32,
    0x4837, 0x18,
    0x4b00, 0x06,
    0x4b01, 0x0a,
    0x4b04, 0x10,
    0x5000, 0xff,
    0x5001, 0x00,
    0x5002, 0x41,
    0x5003, 0x0a,
    0x5004, 0x00,
    0x5043, 0x00,
    0x5013, 0x00,
    0x501f, 0x03,
    0x503d, 0x00,
    0x5780, 0xfc,
    0x5781, 0x1f,
    0x5782, 0x03,
    0x5786, 0x20,
    0x5787, 0x40,
    0x5788, 0x08,
    0x5789, 0x08,
    0x578a, 0x02,
    0x578b, 0x01,
    0x578c, 0x01,
    0x578d, 0x0c,
    0x578e, 0x02,
    0x578f, 0x01,
    0x5790, 0x01,
    0x5a00, 0x08,
    0x5b00, 0x01,
    0x5b01, 0x40,
    0x5b02, 0x00,
    0x5b03, 0xf0,
    0x350b, 0xf0,
    0x0100, 0x01,

};


int32_t OV5648_WriteReg(uint16_t u16_ov5648Reg, uint8_t u8_Val)
{
    uint8_t u8_buf[3] = {0};
    int32_t s32_result = 0;

    u8_buf[0] = u16_ov5648Reg >> 8;
    u8_buf[1] = u16_ov5648Reg & 0xff;
    u8_buf[2] = u8_Val;

    I2C_Master_WriteData(OV5648_COMPONENT, OV5648_I2C_ADDR, u8_buf, 3);
    s32_result = I2C_Master_WaitTillIdle(OV5648_COMPONENT, OV5648_I2C_MAX_DELAY);
    if(0 != s32_result)
    {
        DLOG_Error("write reg error:reg=%x,val=%x", u16_ov5648Reg, u8_Val);
        s32_result = -1;
    }
    else
    {
        ;
    }

    return s32_result;
}

int32_t OV5648_ReadReg(uint16_t u16_Reg, uint8_t *pu8_Val)
{
    uint8_t u8_regBuf[2] = {0};
    uint8_t u8_rdVal = 0;
    int32_t s32_result = 0;
    
    u8_regBuf[0] = u16_Reg >> 8;
    u8_regBuf[1] = u16_Reg & 0xff;

    I2C_Master_ReadData(OV5648_COMPONENT, OV5648_I2C_ADDR, u8_regBuf,2, &u8_rdVal, 1);
    s32_result = I2C_Master_WaitTillIdle(OV5648_COMPONENT, OV5648_I2C_MAX_DELAY);
    if(0 != s32_result) 
    {
        DLOG_Error("read reg error:reg=%x", u16_Reg);
        s32_result = -1;
    }
    else
    {
        ;
    }   

    *pu8_Val = u8_rdVal;

    return s32_result;
}

int32_t OV5648_DownloadFirmware(STRU_CAMERA_REG_VALUE *pst_cfg, uint32_t u32_Size)
{
    register uint16_t u16_regAddr = 0;
    register uint8_t u8_val = 0;
    uint8_t u8_regVal = 0;
    uint32_t u32_i;
    int32_t s32_retVal = 0;

    for (u32_i = 0; u32_i < u32_Size; ++u32_i, ++pst_cfg) 
    {
        u16_regAddr = pst_cfg->u16_regAddr;
        u8_val = pst_cfg->u8_val;

        s32_retVal = OV5648_WriteReg(u16_regAddr, u8_val);
        if (s32_retVal < 0)
        {
            goto err;
        }

    }
err:
    return s32_retVal;
}

void OV5648_ReadChipId(void)
{
    uint8_t Chip_ID[2] = {0, 0};
    
    OV5648_ReadReg(0x300A, &Chip_ID[0]);
    OV5648_ReadReg(0x300B, &Chip_ID[1]);
    DLOG_Warning("OV5648 chip id: 0x%02x", Chip_ID[0]);
    if((0x56 == Chip_ID[0]) && (0x48 == Chip_ID[1]))
    {
        DLOG_Warning("OV5648 chip id ok");
    }
    else
    {
        DLOG_Warning("OV5648 chip id error");
    }
}

void XC6130_OV5648_PinSet(void)
{
    HAL_GPIO_SetMode(XC6130_PWDN, HAL_GPIO_PIN_MODE2);    
    HAL_GPIO_OutPut(XC6130_PWDN);
    HAL_GPIO_SetPin(XC6130_PWDN,  HAL_GPIO_PIN_SET);
    HAL_Delay(5);
    HAL_GPIO_SetPin(XC6130_PWDN,  HAL_GPIO_PIN_RESET);

    
    HAL_GPIO_SetMode(OV5648_RESET, HAL_GPIO_PIN_MODE2);    
    HAL_GPIO_SetMode(OV5648_PWDN, HAL_GPIO_PIN_MODE2);    
    HAL_GPIO_OutPut(OV5648_RESET);
    HAL_GPIO_OutPut(OV5648_PWDN);
    HAL_GPIO_SetPin(OV5648_RESET,  HAL_GPIO_PIN_RESET);
    HAL_GPIO_SetPin(OV5648_PWDN,  HAL_GPIO_PIN_RESET);
    HAL_Delay(3);
    HAL_GPIO_SetPin(OV5648_RESET,  HAL_GPIO_PIN_SET);
    HAL_GPIO_SetPin(OV5648_PWDN,  HAL_GPIO_PIN_SET);
}


void SwitchI2CToOv5648(void)
{
    HAL_I2C_MasterInit(OV5648_COMPONENT, OV5648_I2C_ADDR, HAL_I2C_FAST_SPEED);
    XC6130_I2cByPassOn();
    DLOG_Warning("SwitchI2CToOv5648...");
}

void OV5648_Init(uint8_t par_no)
{
    uint32_t u32_Ov5648ArSize = 0;

    if(0 == par_no)
    {
        
        u32_Ov5648ArSize = sizeof(OV5648_1920_1080_30fps) /
                                    sizeof(OV5648_1920_1080_30fps[0]);
        
        OV5648_DownloadFirmware(OV5648_1920_1080_30fps, u32_Ov5648ArSize);
    }
}
